<template>
    <div :style="{ minHeight: !disabled || uploadFileList.length ? '70px' : '' }">
        <el-upload
            multiple
            :limit="limit"
            :file-list="uploadFileList"
            :headers="headers"
            :action="uploadUrl"
            :accept="accept"
            :before-upload="beforeUpload"
            :disabled="disabled"
            :on-success="fileUploadSuccess"
            :on-exceed="onExceed"
            :on-progress="onProgress"
            list-type="picture-card"
            class="comp-event-file-upload"
            :class="{ 'is-disabled': disabled || uploadFileList.length >= limit }"
        >
            <i slot="default" class="el-icon-plus" style="font-size: 11px"></i>
            <template slot="file" slot-scope="{ file }">
                <div class="select" v-if="currentSelect && currentSelect === file.resourceId"></div>
                <el-image :src="file.url || file.resourceUrl" :alt="file.name || file.fileName" :fit="fit" v-if="file.resourceType == 1" style="width: 70px;height:70px">
                    <div slot="error" class="image-slot">
                        <i class="el-icon-picture-outline"></i>
                    </div>
                </el-image>
                <i class="iconfont icon-linye_icon_luxiang1" v-else-if="file.resourceType == 2"></i>
                <i class="iconfont icon-pc-wenjianzhanwei" v-else-if="file.resourceType == 3"></i>
                <el-progress
                    type="circle"
                    :percentage="file.percentage"
                    v-if="file._status === 'loading'"
                    :show-text="false"
                    :width="50"
                    style="width: 50px;"
                    :stroke-width="3"
                ></el-progress>
                <div class="upload-error" v-else-if="file._status === 'error'">上传失败</div>
                <div class="el-upload-list__item-actions">
                    <span class="el-upload-list__item-preview" @click="handlerPreview(file)" v-if="file._status !== 'error'">
                        <i style='font-size: 16px;' class="el-icon-zoom-in"></i>
                    </span>
                    <span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file)"> <i  style='font-size: 16px;' class="el-icon-delete"></i> </span>
                    <span v-else class="el-upload-list__item-delete" @click="handlerDownload(file)"> <i style='font-size: 16px;' class="el-icon-download"></i> </span>
                </div>
            </template>
        </el-upload>
    </div>
</template>

<script>
import { getToken } from '@/utils/common'
import EventFilePreview from './EventFilePreview.js'
import { downloadByUrl } from '@/utils/download'
import EventBus from '@/components/EventBus'
import FormValid from '@/components/form/FormValid.js'
export default {
    name: 'EventFileUpload',
    mixins: [FormValid],
    props: {
        /**
      * @param {Array} value 文件列表
      * [{
      *  "fileName"：""， //文件名
          "resourceId"：1704162068806，//资源ID
          "resourceType"：1，//资源类型：1:图片 2:视频 3:文件
          "resourceUrl"：""，  //资源url
        }]
      *
      */
        value: {
            type: Array
        },
        // 选中某个文件 resourceId
        selecteResourceId: {
            type: String
        },
        disabled: Boolean,
        accept: {
            type: String,
            default: '.png,.jpg,.jpeg,.pdf,.doc,.docx,.ppt,.pptx,.txt,.mp4'
        },
        limit: {
            type: Number,
            default: 9
        },
        headers: {
            type: Object,
            default() {
                return {
                    Authorization: 'Bearer ' + getToken()
                }
            }
        },
        uploadUrl: {
            type: String,
            default: process.env.VUE_APP_BASE_API + '/file/base/common/upload'
        },
        // 下载图片文件名前缀
        downloadFileName: {
            type: String,
            default: 'downloadFile'
        },
        fit: {
            type: String,
            default: 'cover'
        },
        // 是否正在上传
        loading: {
            type: Boolean,
            default: false
        }
    },
    data() {
        return {
            uploadFileList: [],
            selectId: null
        }
    },
    computed: {
        // 当前选中的资源ID
        currentSelect() {
            return this.selectId || this.selecteResourceId
        }
    },
    methods: {
        // 上传前文件处理
        beforeUpload(file) {
            if (file.size / 1024 / 1024 > 10) {
                this.$message.error(`单个文件上传大小不得超过10M`)
                return false
            }
            const fileType = file.name.substring(file.name.lastIndexOf('.')).toLowerCase()
            const acceptArr = this.accept.split(',')
            // 判断上传文件格式
            if (acceptArr.indexOf(fileType) === -1) {
                this.$message.error(`上传格式仅支持${this.accept.replaceAll('.', '').replaceAll(',', '、')}`)
                return false
            } else {
                if (['.png', '.jpg', '.jpeg', '.bmp'].includes(fileType)) {
                    file.resourceType = 1
                    file.url = URL.createObjectURL(file)
                } else if (['.mp4', '.avi'].includes(fileType)) {
                    file.resourceType = 2
                } else {
                    file.resourceType = 3
                }
            }
            this.$set(file, '_status', 'loading')
            this.$set(file, 'percentage', 0)
            if (!this.loading) this.$emit('update:loading', true)
            this.uploadFileList.push(file)
        },
        // 超出上传数量
        onExceed() {
            this.$message.error('最多上传' + this.limit + '个文件!')
        },

        // 预览
        handlerPreview(file) {
            const files = this.uploadFileList
                .filter((item) => item._status === 'done')
                .map(({ previewUrl, resourceUrl, resourceId, resourceType, fileName, name }) => ({
                    resourceUrl: previewUrl || resourceUrl,
                    resourceId,
                    resourceType,
                    fileName: fileName || name
                }))
            EventFilePreview.show({
                files,
                initialIndex: this.uploadFileList.indexOf(file)
            })
        },
        // 移除
        async handleRemove(file) {
            this.uploadFileList.splice(this.uploadFileList.indexOf(file), 1)
            this.submitEvent()
        },
        // 进度
        onProgress(event, file) {
            file.percentage = event.percent
            this.$forceUpdate()
        },
        // 上传成功
        fileUploadSuccess({ data, code, msg }, file) {
            if (code === 200) {
                file._status = 'done'
                file.resourceId = data.fileId
                file.resourceUrl = data.originUrl
                file.previewUrl = data.fileUrl
            } else {
                file._status = 'error'
                this.$message.error(msg || '文件上传失败')
            }
            this.$forceUpdate()
            if (this.uploadFileList.every((item) => item._status !== 'loading')) {
                this.$emit('update:loading', false)
                this.submitEvent()
            }
        },
        // 更新绑定数据
        submitEvent() {
            const files = this.uploadFileList
                .filter((item) => item._status === 'done')
                .map(({ name, resourceType, resourceId, resourceUrl }) => ({ fileName: name, resourceType, resourceId, resourceUrl }))

            this.$emit('input', files)
            this._dispatch('ElFormItem', 'el.form.change', files)
        },
        // 下载
        handlerDownload(file) {
            downloadByUrl(file.previewUrl || file.resourceUrl, file.fileName || this.downloadFileName + new Date().valueOf())
        }
    },
    watch: {
        // 初始化绑定数据，当数据变化， 过滤重复数据，维持uploadFileList的数据
        value: {
            handler(val) {
                if (val) {
                    val.map((item) => {
                        const node = this.uploadFileList.find((file) => item.resourceId && file.resourceId && file.resourceId === item.resourceId)
                        if (node) {
                            Object.assign(node, item)
                        } else {
                            this.uploadFileList.push({
                                ...item,
                                name: item.fileName,
                                _status: 'done'
                            })
                        }
                    })
                }
            },
            immediate: true
        }
    },
    mounted() {
        // 监听地图点击事件，选中资源
        EventBus.$on('eventMapArrowClickToResource', (resourceId) => (this.selectId = resourceId))
    },
    destroyed() {
        EventBus.$off('eventMapArrowClickToResource')
    }
}
</script>
<style lang="scss" scoped>
.comp-event-file-upload {
    /deep/.el-upload-list {
        .el-upload-list__item {
            width: 70px;
            height: 70px;
            line-height: 70px;
            float: left;
            text-align: center;
            border: none;
            background-color: #f5f7fa;
            margin: 0 12px 12px 0;

            .iconfont {
                font-size: 30px;
                color: #1890ff;
            }

            .upload-error {
                position: absolute;
                bottom: 0px;
                width: 100%;
                height: 20px;
                text-align: center;
                background: rgba(0, 0, 0, 0.1);
                color: #ffa940;
                font-size: 12px;
                line-height: 20px;
            }
        }
    }
    /deep/.el-upload--picture-card {
        &:hover{
            border: 1px dashed #C0C4CC;
        }
        width: 70px;
        height: 70px;
        line-height: 70px;
        float: left;
        background: #f5f7fa;
        border: 1px dashed #d9d9d9;
    }
    .el-upload-list__item-actions {
        font-size: 12px;
        display: flex;
        justify-content: center;
        align-items: center;
        .el-upload-list__item-delete {
            margin-left: 13px;
        }
    }
    .select {
        position: absolute;
        width: 100%;
        height: 100%;
        left: 0;
        top: 0;
        border-radius: 6px;
        border: 2px solid var(--theme);
        z-index: 1;
    }
}
.is-disabled {
    /deep/ .el-upload--picture-card {
        display: none;
    }
}

/deep/ .el-upload-list--picture-card .el-upload-list__item-actions:hover{
    // opacity: 0.7;
    background: rgba(0, 0, 0, .7);
}

</style>
